#ifndef CLUSTERTYPE_H
#define CLUSTERTYPE_H

//#define CLUSTER_WIN32_SWITCH
//#define CLUSTER_UT_TEST

#define CLUSTER_MRS_COMMON_FLAG           0x40000000

#define ROS_LOOP_FREQUENCY                50

#define CLUSTER_MAX_NODE_NUM              10
#define CLUSTER_MAX_TARGET_NUM            10
#define CLUSTER_MAX_PATH_NUM              10
#define CLUSTER_MAX_MSG_CONTAINER_NUM     10

#define CLUSTER_INVALID_ID                0xFFFF
#define CLUSTER_RECV_ID_ALL               CLUSTER_MAX_NODE_NUM
#define CLUSTER_QGC_ID                    0
#define CLUSTER_STATE_LOCK_TIME           300

#ifdef CLUSTER_WIN32_SWITCH
#define CLUSTER_PRINT(REPORT_STRING, ...) printf("%s->Line[%u]:" REPORT_STRING "\n",__FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define CLUSTER_PRINT(REPORT_STRING, arg...) printf("%s->Line[%u]:" REPORT_STRING "\n",__FUNCTION__, __LINE__, ##arg)
#endif
#define CLUSTER_WAIT_ANY_LETTER() do{char aString[10]; int i = scanf("%s",aString);}while(0)

/*前缀字母c：标识此类型名仅在集群代码中有效，其他开发环境应使用对应的类型*/
typedef unsigned char      cUint8;
typedef unsigned short     cUint16;
typedef unsigned int       cUint32;
typedef unsigned long long cUint64;

typedef char      cInt8;
typedef short     cInt16;
typedef int       cInt32;
typedef long long cInt64;

typedef float  cFloat32;
typedef double cFloat64;
/*前缀字母c：标识此类型名仅在集群代码中有效，其他开发环境应使用对应的类型*/

union Cluster_Point{
    cFloat64 aArray[3];
    struct
    {
        cFloat64 x;
        cFloat64 y;
        cFloat64 z;
    }stPoint;
};

struct Cluster_Path_Buf{
    cUint32 uPathNum;
    Cluster_Point aPathPointBuf[CLUSTER_MAX_PATH_NUM];
};

enum Cluster_Command
{
    CLUSTER_COMMAND_NONE,
    /*Cluster command area*/
    /*集群主节点产生的消息，接收即执行！*/
    CLUSTER_COMMAND_STATE_SYNC,//主节点做状态同步，可以用在切换后通知其他子节点目前的主节点号
    CLUSTER_COMMAND_SUBNODE_START,
    CLUSTER_COMMAND_SUBNODE_END,
    CLUSTER_COMMAND_MISSION_START,
    CLUSTER_COMMAND_MISSION_END,
    CLUSTER_COMMAND_SCAN_START,
    CLUSTER_COMMAND_TARGET_ASSIGN,/*7*/

    CLUSTER_COMMAND_STATE_SYNC_RESP,
    CLUSTER_COMMAND_SUBNODE_START_RESP,
    CLUSTER_COMMAND_SUBNODE_END_RESP,
    CLUSTER_COMMAND_MISSION_START_RESP,
    CLUSTER_COMMAND_MISSION_END_RESP,
    CLUSTER_COMMAND_SCAN_START_RESP,
    CLUSTER_COMMAND_TARGET_ASSIGN_RESP,/*14*/

    /*集群所有节点都会产生的消息，接收即执行！*/
    CLUSTER_COMMAND_STATE_REPORT,
    CLUSTER_COMMAND_DEDI_CONN_REQ,
    CLUSTER_COMMAND_DEDI_CONN_SETUP,
    CLUSTER_COMMAND_DEDI_CONN_RESP,

    /*User command area*/
    /*用户下发的命令，发送给主节点，主节点接收后保存，每个节点都保存，但由主节点再次下发命令决定是否执行！*/
    CLUSTER_COMMAND_FORMATION,
    CLUSTER_COMMAND_NODE_CREATE_CLOSE,
    CLUSTER_COMMAND_FORMATION_RESP,
    CLUSTER_COMMAND_NODE_CREATE_CLOSE_RESP,

    CLUSTER_COMMAND_CONTEXT_SAVE,
    CLUSTER_COMMAND_USER_CTRL,/*24*/

    /*Member special command area*/
    /*用户定制的命令，也由用户下发，每个厂家均不一样！*/
    CLUSTER_COMMAND_YX_POWER_ON_COMMAND,
    CLUSTER_COMMAND_YX_JB_COMMAND,
    CLUSTER_COMMAND_THROW_COMMAND,
};

enum Cluster_Network_State
{
    CLUSTER_NETWORK_STATE_NONE,
    CLUSTER_NETWORK_STATE_CREATE_CLUSTER,
    CLUSTER_NETWORK_STATE_NORMAL,
    CLUSTER_NETWORK_STATE_ABNORMAL_RESUME,

    /*特殊状态，其他节点置为此状态时，代表单机不可达，本机置为此状态时，代表多数单体不可达*/
    CLUSTER_NETWORK_STATE_ABNORMAL,
};

enum Cluster_SubNode_State
{
    CLUSTER_SUBNODE_STATE_NONE,
    CLUSTER_SUBNODE_STATE_STARTING,
    CLUSTER_SUBNODE_STATE_GO_FORMATION,
    CLUSTER_SUBNODE_STATE_STANDBY,
    CLUSTER_SUBNODE_STATE_GO_POINT,
    CLUSTER_SUBNODE_STATE_SCANNING,
    CLUSTER_SUBNODE_STATE_AUTOWORK,/*自主寻找目标过程*/
    CLUSTER_SUBNODE_STATE_USER_CONTROL,
    CLUSTER_SUBNODE_STATE_ENDING,
};

enum Cluster_Mission_State
{
    CLUSTER_MISSION_STATE_NONE,
    CLUSTER_MISSION_STATE_GO_DEST,
    CLUSTER_MISSION_STATE_SCANNING,
    CLUSTER_MISSION_STATE_WORKING,
    CLUSTER_MISSION_STATE_RETURN,
    CLUSTER_MISSION_STATE_PERIPHERAL_ABNORMAL,
    CLUSTER_MISSION_STATE_SELF_DESTROY,
};

enum Cluster_Work_State
{
    CLUSTER_WORK_STATE_NONE,
    CLUSTER_WORK_STATE_REVOKABLE,
    CLUSTER_WORK_STATE_UNREVOKABLE,
    CLUSTER_WORK_STATE_SUCCESS,
    CLUSTER_WORK_STATE_FAILURE,
    CLUSTER_WORK_STATE_NO_TARGET,
    CLUSTER_WORK_STATE_INVALID,
};

enum Cluster_Target_State
{
    CLUSTER_TARGET_STATE_NONE,
    CLUSTER_TARGET_STATE_FIND,
    CLUSTER_TARGET_STATE_LOST,
    CLUSTER_TARGET_STATE_ABNORMAL,
    CLUSTER_TARGET_STATE_ASSIGNED,
    CLUSTER_TARGET_STATE_WORK_SUCCESS,
    CLUSTER_TARGET_STATE_WORK_FAILURE,
};

enum Cluster_Formation_Type
{
    CLUSTER_FORMATION_LINE,
    CLUSTER_FORMATION_TRIANGLE,
    CLUSTER_FORMATION_CROSS,
};

enum Cluster_Node_Type
{
    CLUSTER_NODE_TYPE_NONE,
    CLUSTER_NODE_TYPE_SUBNODE,
    CLUSTER_NODE_TYPE_MAINNODE,
    CLUSTER_NODE_TYPE_MULTINODE,
};

enum Cluster_Message_Type
{
    CLUSTER_MSG_TYPE_NONE,
    CLUSTER_MSG_TYPE_STATE,
    CLUSTER_MSG_TYPE_CONTROL,
};

struct Cluster_Message_Header
{
    cUint32 uSN;
    cUint32 uSendID;
    cUint32 uRecvID;
    cUint32 uMainNodeID;
    cUint32 uSelectIDNum;
    cUint32 auSelectID[CLUSTER_MAX_NODE_NUM];
    Cluster_Command enClusterCmd;
};

/*|         |         |         |         |         |         |         |         |         |         |
**|         SN        |      send ID      |      Recv ID      |    Main Node ID   |  Select Node ID   |
**| QGC IE  |……*/
enum Cluster_Optional_IE
{
    /*State Message*/
    CLUSTER_OPTIONAL_IE_INITIAL_POS,
    CLUSTER_OPTIONAL_IE_INITIAL_POS_GPS,
    CLUSTER_OPTIONAL_IE_OFFSET_POS,
    CLUSTER_OPTIONAL_IE_OFFSET_POS_GPS,
    CLUSTER_OPTIONAL_IE_GLOBAL_POS,
    CLUSTER_OPTIONAL_IE_GLOBAL_POS_GPS,
    CLUSTER_OPTIONAL_IE_MEMBER_VEL,
    CLUSTER_OPTIONAL_IE_NETWORK_STATE,
    CLUSTER_OPTIONAL_IE_SUBNODE_STATE,
    CLUSTER_OPTIONAL_IE_MISSION_STATE,
    CLUSTER_OPTIONAL_IE_WORK_STATE,

    /*State Message*/
    CLUSTER_OPTIONAL_IE_TARGET_INFO,

    /*State Message*/
    CLUSTER_OPTIONAL_IE_COMMON_PATH_INDEX,
    CLUSTER_OPTIONAL_IE_SUBNODE_MAP_ID,
    CLUSTER_OPTIONAL_IE_PATH_POINT,
    CLUSTER_OPTIONAL_IE_PATH_POINT_GPS,
    CLUSTER_OPTIONAL_IE_FORMATION_POS,
    CLUSTER_OPTIONAL_IE_TARGET_ID,
    CLUSTER_OPTIONAL_IE_FORMATION_TYPE,
    CLUSTER_OPTIONAL_IE_SCAN_AREA,
    CLUSTER_OPTIONAL_IE_SCAN_AREA_GPS,
    CLUSTER_OPTIONAL_IE_PICKUP_POINT,
    CLUSTER_OPTIONAL_IE_PICKUP_POINT_GPS,
    CLUSTER_OPTIONAL_IE_VELOCITY_CMD,
    CLUSTER_OPTIONAL_IE_CAUSE,//字符串，传递模块间交互的语言信息
};

/*集群中单体之间交换的状态：1、飞机自身的全局位置；2、飞机自身的全局速度；3、飞机当前的运行状态；4、飞机当前任务执行状态；
5、基于当前飞机解算的目标全局位置*/
#define CLUSTER_SUBNODE_MSG_IE_INITIAL_POS           0x0001
#define CLUSTER_SUBNODE_MSG_IE_OFFSET_POS            0x0002
#define CLUSTER_SUBNODE_MSG_IE_GLOBAL_POS            0x0004
#define CLUSTER_SUBNODE_MSG_IE_VELOCITY              0x0008
#define CLUSTER_SUBNODE_MSG_IE_NETWORK_STATE         0x0010
#define CLUSTER_SUBNODE_MSG_IE_SUBNODE_STATE         0x0020
#define CLUSTER_SUBNODE_MSG_IE_MISSION_STATE         0x0040
#define CLUSTER_SUBNODE_MSG_IE_WORK_STATE            0x0080
#define CLUSTER_SUBNODE_MSG_IE_TARGET_POS            0x0100

struct Cluster_State_Message
{
    cUint32 uEncodeDirectField;
    Cluster_Message_Header stMsgHeader;
    Cluster_Point stSubNodeInitialPos;
    Cluster_Point stSubNodeOffsetPos;
    Cluster_Point stSubNodeGlobalPos;
    Cluster_Point stSubNodeVelocity;
    Cluster_Network_State enClusterNetworkState;
    Cluster_SubNode_State enClusterSubNodeState;
    Cluster_Mission_State enClusterMissionState;
    Cluster_Work_State enClusterWorkState;
    Cluster_Path_Buf stTargetGlobalPos;
};

/*用户命令：1、下发寻飞区域；2、寻飞区域更改命令；3、单/群体起飞命令；4、单/群体降落命令；5、单/群体开始命令；
6、单/群体返航命令；7、单/群体保持命令；8、群体队形变换命令；9、单/群体移动命令*/
#define CLUSTER_MAINNODE_MSG_IE_SUBNODE_MAP_ID          0x0001
#define CLUSTER_MAINNODE_MSG_IE_PATH_POINT              0x0002
#define CLUSTER_MAINNODE_MSG_IE_PATH_POINT_GPS          0x0004
#define CLUSTER_MAINNODE_MSG_IE_FORMATION_POS           0x0008
#define CLUSTER_MAINNODE_MSG_IE_ASSIGN_TARGET_ID        0x0010
#define CLUSTER_MAINNODE_MSG_IE_TARGET_POS_ALL          0x0020
#define CLUSTER_MAINNODE_MSG_IE_COMMON_PATH_INDEX       0x0040
#define CLUSTER_MAINNODE_MSG_IE_FORMATIPN_TYPE          0x0080
#define CLUSTER_MAINNODE_MSG_IE_AREA_INFO               0x0100
#define CLUSTER_MAINNODE_MSG_IE_AREA_INFO_GPS           0x0200
#define CLUSTER_MAINNODE_MSG_IE_PICKUP_POINT            0x0400
#define CLUSTER_MAINNODE_MSG_IE_PICKUP_POINT_GPS        0x0800
#define CLUSTER_MAINNODE_MSG_IE_VELOCITY                0x1000

struct Cluster_Control_Message
{
    cUint32 uEncodeDirectField;
    Cluster_Message_Header stMsgHeader;
    cUint32 uSubNodeNumber;
    /*主节点一次将所有Path信息发送给子节点，并通过uCurrExecPathPointIndex决定目前执行哪个路径点*/
    cUint32 uCurrExecPathPointIndex;
    cUint32 auSubNodeMapID[CLUSTER_MAX_NODE_NUM];
    Cluster_Path_Buf *pastSubNodePathPoint[CLUSTER_MAX_NODE_NUM];
    Cluster_Point astFormationPos[CLUSTER_MAX_NODE_NUM];
    cUint32 auSubNodeAssignTargetID[CLUSTER_MAX_NODE_NUM];
    Cluster_Path_Buf stTargetGlobalPos;
    Cluster_Formation_Type enFormationType;
    Cluster_Path_Buf stScanArea;//目前目标区域仅接受四边形
    Cluster_Point stPickupPoint;
    cFloat32 velocityLimit;
};

union Cluster_Message_Content
{
    Cluster_Control_Message stControlMessage;
    Cluster_State_Message stStateMessage;
};

struct Cluster_Message_Info
{
    Cluster_Message_Type aenClusterMsgType[CLUSTER_MAX_MSG_CONTAINER_NUM];
    Cluster_Message_Content *pastMessageCntnt[CLUSTER_MAX_MSG_CONTAINER_NUM];
};

struct Cluster_Operator_Context
{
    cUint32 uEncodeDirectField;
    Cluster_Message_Header stMsgHeader;
    Cluster_Formation_Type enFormationType;
    Cluster_Path_Buf stScanArea;//目前目标区域仅接受四边形
    Cluster_Path_Buf stPathPoint;//操作者路径暂时存储到stCommonPathPoint，目前先不考虑需要区分的场景
    Cluster_Point stPickupPoint;
    cFloat64 aMapScanInfo[6];/*对scanArea解析，Array[0]=AreaLen,Array[1]=AreaWidth,Array[2-4]=AreaCenterX-Z,Array[5]=UavNormalNum*/
    cFloat32 velocityLimit;
};

struct Cluster_SubNode_Context
{
    cUint32 uSubNodeAssignTargetID;
    cUint32 uCurrentPathPointIndex;
    Cluster_Point stSubNodeInitialPos;
    Cluster_Point stSubNodeOffsetPos;
    Cluster_Point stSubNodeGlobalPos;
    Cluster_Point stFormationOffsetPos;
    Cluster_Point stSubNodeVelocity;
    Cluster_Path_Buf stSubNodePath;
    Cluster_Path_Buf stTargetPos;
};

struct Cluster_State_Context
{
    Cluster_Network_State enClusterNetworkState;
    Cluster_SubNode_State enClusterSubNodeState;
    Cluster_Mission_State enClusterMissionState;
    Cluster_Work_State enClusterWorkState;
    cUint32 uClusterChangeStateLockTime;
    cUint32 uMemberChangeStateLockTime;
};

struct Cluster_Target_Context
{
    cUint32 uTargetExecCount;
    Cluster_Target_State enTargetState;
    Cluster_Point stTargetGlobalPos;
};

struct Cluster_Context
{
    cUint32 uCurrentID;
    cUint32 uMainNodeID;
    cUint32 uQGCID;/*QGroundControl ID is 0xFFFF, So no veriable of ground control station!*/
    Cluster_Node_Type enClusterNodeType;

    /*存储操作者命令信息*/
    Cluster_Command enPendingOperatorCmd;
    Cluster_Operator_Context stOperatorCntxt;

    /*存储主节点或公共信息*/
    bool bIsCommonPathUsed;
    //cUint32 uCommonPathNum;
    cUint32 uCommonPathCurrentIndex;
    //Cluster_Point astCommonPathPoint[CLUSTER_MAX_PATH_NUM];
    Cluster_Path_Buf stCommonPathPoint;

    /*存储成员总体信息*/
    cUint32 uSubNodeNum;
    cUint32 uNormalSubNodeNum;
    cUint32 uAvailableSubNodeNum;
    cUint32 auSubNodeMapID[CLUSTER_MAX_NODE_NUM];

    /*存储成员单体信息*/
    Cluster_Point astInterUavDistance[CLUSTER_MAX_NODE_NUM];
    Cluster_SubNode_Context astSubNodeCntxt[CLUSTER_MAX_NODE_NUM];
    Cluster_State_Context astSubNodeState[CLUSTER_MAX_NODE_NUM];

    /*存储目标总体信息*/
    cUint32 uTargetAllNum;
    cUint32 uTargetRemainNum;
    cUint32 uTargetAbnormalNum;

    /*存储目标单体信息*/
    Cluster_Target_Context astTargetCntxt[CLUSTER_MAX_TARGET_NUM];
};
/**************************************************************************************************************************************/

extern Cluster_Context *fnCluster_ctrl_GetClusterCntxt(void);
extern cUint32 fnCluster_codec_EncodeMessage(cUint8 *pOutMsgStream, Cluster_Message_Info *pstEncodeMsg);
extern void fnCluster_codec_DecodeMessage(cUint8 *pInMsgStream, cUint32 uInMsgLen, Cluster_Message_Info *pstDecodeMsg);
extern void fnCluster_mh_SaveStateMessage(Cluster_Context *pstClusterContext, Cluster_State_Message *pstSubNodeMsg);
extern void fnCluster_mh_SaveControlMessage(Cluster_Context *pstClusterContext, Cluster_Control_Message *pstMainNodeMsg);
extern void fnCluster_codec_FourByteToStream(cUint8 *pOutMsgStream, cUint32 *puSourceVal);
extern void *fnCluster_buf_AllocBuf(cUint32 uSize);
extern bool fnCluster_buf_FreeBuf(cUint8 *pBuf);

#endif // CLUSTERTYPE_H
